package ai4games_tests.tests;

import game2dai.Domain;
import game2dai.World;
import game2dai.entities.Vehicle;
import game2dai.entityshapes.ps.ArrowPic;
import game2dai.entityshapes.ps.Hints;
import game2dai.maths.Vector2D;
import game2dai.steering.AutoPilot;
import game2dai.utils.Message;
import game2dai.utils.StopWatch;
import processing.core.PApplet;

// Flocking
public class GameTest_009 extends PApplet {

	final boolean HINTS = false;
	final int NBR_BOIDS = 200;
	
	World w;
	Domain wd;
	
	StopWatch sw = new StopWatch();
	
	Vehicle boid;
	Vehicle[] boids;
	AutoPilot sb;
	AutoPilot[] sbarray;
	ArrowPic view;
	int count = 0;
	float deltaTime;

	public void setup(){
		  size(800, 600);
		  w = new World(width, height, 50 ,0);
		  wd = new Domain(0, 0, width - 200, height);
		  w.noOverlap(false);

		  sb = new AutoPilot();
//		  sb.enableBehaviours(SBF.WANDER | SBF.FLOCK);
		  sb.wanderOn().flockOn();
//		  sb.setWanderDetails(500, 50, 100);	  
		  sb.wanderFactors(100, 10, 500);
		  
		  sb.flockFactors(50);
		  sb.wanderWeight(1);
		  sb.alignmentWeight(8);
		  sb.cohesionWeight(2.2);
		  sb.separationWeight(1.3);
		  sb.flockWeight(16.0);

		  boids = new Vehicle[NBR_BOIDS];
		  sbarray = new AutoPilot[NBR_BOIDS];
		  for (int i = 0; i < NBR_BOIDS; i++) {
		    float dirX = (rnd(0, 1) < 0.5) ? -1 : 1;
		    float dirY = (rnd(0, 1) < 0.5) ? -1 : 1;
		    float x = dirX * rnd(5, 10);
		    float y = dirY * rnd(5, 10);
		    boid = new Vehicle(new Vector2D(), // position
		        5, // collision radius
		        new Vector2D(x, y), // velocity
		        60, // maximum speed
		        new Vector2D(x, y), // heading
		        1, // mass
		        10, // turning rate
		        400 // max force
		        ); 
		    view = new ArrowPic(this, 7, color(220, 220, 255), color(220, 220, 255), 1);	
			view.showHints(Hints.HINT_HEADING | Hints.HINT_VELOCITY);
		    boid.renderer(view);
		    boids[i] = boid;
		    sbarray[i] = (AutoPilot) sb.clone();
		    boid.AP(sbarray[i]);
		    boid.worldDomain(wd);
		    w.add(boid);
		  }
		  resetBoids();
		  sw.reset();
		}
	
	
	public void draw(){
		deltaTime = (float) sw.getElapsedTime();
		
		background(0,0,64);
		fill(0,64,0);
		noStroke();
		
		w.update(deltaTime);
		w.draw();
		if(++count % 100 == 0){
			println(frameRate + "\t" + w.worldUpdateTime);
		}
	}

	public void keyReleased(){
		if(key == ' ')
			resetBoids();
	}
	
	public void resetBoids(){
		int nm = w.nbr_movers;
		for (int i = 0; i < NBR_BOIDS; i++) {
			boids[i].die(w, 0);
//			w.remove(boids[i]);
			float x = (width - 200)/2 + random(-200, 200);
			float y = height/2 + random(-200, 200);
			float dirX = (rnd(0, 1) < 0.5) ? -1 : 1;
			float dirY = (rnd(0, 1) < 0.5) ? -1 : 1;
			float vx = dirX * rnd(5, 10);
			float vy = dirY * rnd(5, 10);
			boids[i].moveTo(x,y);
			boids[i].heading(vx,vy);
			boids[i].velocity(vx,vy);
		}
		for (int i = 0; i < NBR_BOIDS; i++) {
			w.add(boids[i]);
		}
		Message.println("Reset boids from {0} to {1}", nm, w.nbr_movers);
	}

	public float rnd(float low, float high){
		return (float)Math.random()*(high - low) + low;
	}
}
